home *** CD-ROM | disk | FTP | other *** search
/ EnigmA Amiga Run 1996 March / EnigmA AMIGA RUN 05 (1996)(G.R. Edizioni)(IT)[!][issue 1996-03][Skylink CD IV].iso / earcd / program / ixemlsrc.lha / ixemul / library / statfs.c < prev    next >
C/C++ Source or Header  |  1995-12-23  |  10KB  |  372 lines

  1. /*
  2.  *  This file is part of ixemul.library for the Amiga.
  3.  *  Copyright (C) 1991, 1992  Markus M. Wild
  4.  *
  5.  *  This library is free software; you can redistribute it and/or
  6.  *  modify it under the terms of the GNU Library General Public
  7.  *  License as published by the Free Software Foundation; either
  8.  *  version 2 of the License, or (at your option) any later version.
  9.  *
  10.  *  This library is distributed in the hope that it will be useful,
  11.  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
  12.  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  13.  *  Library General Public License for more details.
  14.  *
  15.  *  You should have received a copy of the GNU Library General Public
  16.  *  License along with this library; if not, write to the Free
  17.  *  Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  18.  *
  19.  *  statfs.c,v 1.1.1.1 1994/04/04 04:31:00 amiga Exp
  20.  *
  21.  *  statfs.c,v
  22.  * Revision 1.1.1.1  1994/04/04  04:31:00  amiga
  23.  * Initial CVS check in.
  24.  *
  25.  *  Revision 1.2  1992/08/09  21:00:32  amiga
  26.  *  add alternate fs id's...
  27.  *
  28.  *  Revision 1.1  1992/05/22  01:50:27  mwild
  29.  *  Initial revision
  30.  *
  31.  */
  32.  
  33. #define KERNEL
  34. #include "ixemul.h"
  35. #include "kprintf.h"
  36. #include <sys/mount.h>
  37. #include <string.h>
  38.  
  39. #ifndef ID_FFS_DISK
  40. #define ID_FFS_DISK        (0x444F5301L)    /* 'DOS\1' */
  41. #define ID_INTER_DOS_DISK    (0x444F5302L)    /* 'DOS\2' */
  42. #define ID_INTER_FFS_DISK    (0x444F5303L)    /* 'DOS\3' */
  43. #define ID_MSDOS_DISK        (0x4d534400L)    /* 'MSD\0' */
  44. #endif
  45.  
  46. /* no comments here ;-) */
  47. #define ID_ALT_OFS_DISK        (0x444F5304L)    /* 'DOS\4' */
  48. #define ID_ALT_FFS_DISK        (0x444F5305L)    /* 'DOS\5' */
  49. #define ID_ALT_INTER_DOS_DISK    (0x444F5306L)    /* 'DOS\6' */
  50. #define ID_ALT_INTER_FFS_DISK    (0x444F5307L)    /* 'DOS\7' */
  51.  
  52. /* dunno, would be logical ;-)) */
  53. #define ID_NFS_DISK        (0x4E465300)    /* 'NFS\0' */    
  54. /* did somebody already do this ??? */
  55. #define ID_UFS_DISK        (0x55465300)    /* 'UFS\0' */    
  56.  
  57.  
  58. /* this function fills in InfoData information from a statfs structure
  59.    that has at least its f_fsid field set to the handler */
  60.  
  61. static void
  62. internal_statfs (struct statfs *buf, struct InfoData *info, struct StandardPacket *sp)
  63. {
  64.   sp->sp_Pkt.dp_Port = u.u_sync_mp;
  65.   sp->sp_Pkt.dp_Type = ACTION_DISK_INFO;
  66.   sp->sp_Pkt.dp_Arg1 = CTOBPTR (info);
  67.   PutPacket ((struct MsgPort *) buf->f_fsid.val[0], sp);
  68.   __wait_sync_packet (sp);
  69.       
  70.   /* if packet is implemented on handler side */
  71.   if (sp->sp_Pkt.dp_Res1 == -1)
  72.     {
  73.       struct DeviceList *dl = BTOCPTR (info->id_VolumeNode);
  74.  
  75.       if (dl)
  76.     {
  77.           char *name = BTOCPTR (dl->dl_Name);
  78.       int len = (MNAMELEN - 2 < name[0]) ? MNAMELEN - 2 : name[0];
  79.  
  80.       /* use this field to represent the volume name */
  81.           bcopy (name + 1, buf->f_mntfromname + 1, len);
  82.           buf->f_mntfromname[0] = '/';
  83.           buf->f_mntfromname[len + 1] = 0;
  84.         }
  85.       else
  86.     /* for stuff like FIFO that doesn't have an associated volume */
  87.     strcpy (buf->f_mntfromname, buf->f_mntonname);
  88.  
  89.       switch (info->id_DiskType)
  90.         {
  91.         case ID_DOS_DISK:
  92.         case ID_ALT_OFS_DISK:
  93.           buf->f_type = MOUNT_ADOS_OFS;
  94.       break;
  95.           
  96.     case ID_FFS_DISK:
  97.     case ID_ALT_FFS_DISK:
  98.       buf->f_type = MOUNT_ADOS_FFS;
  99.       break;
  100.  
  101.     case ID_INTER_DOS_DISK:
  102.     case ID_ALT_INTER_DOS_DISK:
  103.       buf->f_type = MOUNT_ADOS_IOFS;
  104.       break;
  105.  
  106.     case ID_INTER_FFS_DISK:
  107.     case ID_ALT_INTER_FFS_DISK:
  108.       buf->f_type = MOUNT_ADOS_IFFS;
  109.       break;
  110.  
  111.     case ID_MSDOS_DISK:
  112.       buf->f_type = MOUNT_PC;
  113.       break;
  114.       
  115.     case ID_NFS_DISK:
  116.       buf->f_type = MOUNT_NFS;
  117.       break;
  118.       
  119.     case ID_UFS_DISK:
  120.       buf->f_type = MOUNT_UFS;
  121.       break;
  122.  
  123.     default:          
  124.       buf->f_type = MOUNT_NONE;
  125.       break;
  126.     }
  127.         
  128.       buf->f_flags  = MNT_NOSUID | MNT_NODEV;
  129.       if (info->id_DiskState != ID_VALIDATED)
  130.         /* can be ID_WRITE_PROTECTED or ID_VALIDATING */
  131.     buf->f_flags |= MNT_RDONLY;
  132.         
  133.       buf->f_fsize  = info->id_BytesPerBlock;
  134.       buf->f_bsize  = info->id_BytesPerBlock * ix.ix_fs_buf_factor;
  135.       buf->f_blocks = info->id_NumBlocks;
  136.       buf->f_bfree =
  137.         buf->f_bavail = info->id_NumBlocks - info->id_NumBlocksUsed;
  138.       /* no inode information available, thus set to -1 */
  139.       buf->f_files =
  140.       buf->f_ffree = -1;
  141.    }
  142. }
  143.  
  144.  
  145.  
  146. int
  147. getfsstat (struct statfs *buf, long bufsize, int flags)
  148. {
  149.   int num_devs = 0;
  150.   struct statfs *orig_buf = buf;
  151.   long orig_bufsize = bufsize;
  152.   
  153.   struct DosLibrary *dl;
  154.   struct RootNode *rn;
  155.   struct DosInfo *di;
  156.   struct DevInfo *dv;
  157.   extern struct ixemul_base *ixemulbase;
  158.   
  159.   struct InfoData *info;
  160.   struct StandardPacket *sp;
  161.  
  162.   /* could probably use less drastic measures under 2.0... */
  163.   Forbid ();
  164.   dl = DOSBase;
  165.   rn = (struct RootNode *) dl->dl_Root;
  166.   di = BTOCPTR (rn->rn_Info);
  167.   for (dv = BTOCPTR (di->di_DevInfo); dv; dv = BTOCPTR (dv->dvi_Next))
  168.     {
  169.       if (dv->dvi_Type == DLT_DEVICE && dv->dvi_Task && dv->dvi_Name)
  170.     {
  171.       num_devs ++;
  172.       if (buf && bufsize >= sizeof (*buf))
  173.         {
  174.           char *name = BTOCPTR (dv->dvi_Name);
  175.           int len = (MNAMELEN - 2 < name[0]) ? MNAMELEN - 2 : name[0];
  176.  
  177.           /* only remember the name and the address of the
  178.              handler so that we can later send INFO packets there */
  179.           bzero (buf, sizeof (*buf));
  180.           bcopy (name + 1, buf->f_mntonname + 1, len);
  181.           buf->f_mntonname[0] = '/';
  182.           buf->f_mntonname[len + 1] = 0;
  183.           buf->f_fsid.val[1] = 0;
  184.           buf->f_fsid.val[0] = (long) dv->dvi_Task;
  185.           
  186.           buf++;
  187.           bufsize -= sizeof (struct statfs);
  188.         }
  189.     }
  190.     }
  191.   Permit ();
  192.  
  193.   if (! orig_buf || orig_bufsize < sizeof (struct statfs))
  194.     return num_devs;
  195.  
  196.   info = alloca (sizeof (*info) + 2);
  197.   info = LONG_ALIGN (info);
  198.  
  199.   sp = alloca (sizeof (*sp) + 2);
  200.   sp = LONG_ALIGN (sp);
  201.   __init_std_packet (sp);
  202.  
  203.   /* have a second run, and inquire more data from the associated volumes */
  204.   while (orig_buf < buf)
  205.     {
  206.       internal_statfs (orig_buf, info, sp);
  207.       orig_buf++;
  208.     }
  209.  
  210.   return num_devs;
  211. }
  212.  
  213. int
  214. fstatfs (int fd, struct statfs *buf)
  215. {
  216.   struct file *f = u.u_ofile[fd];
  217.   struct DosLibrary *dl;
  218.   struct RootNode *rn;
  219.   struct DosInfo *di;
  220.   struct DevInfo *dv;
  221.   extern struct ixemul_base *ixemulbase;
  222.   
  223.   struct InfoData *info;
  224.   struct StandardPacket *sp;
  225.  
  226.   if ((unsigned)fd < NOFILE && f)
  227.     {
  228.       if (! buf)
  229.         {
  230.           errno = EFAULT;
  231.       KPRINTF (("&errno = %lx, errno = %ld\n", &errno, errno));
  232.           return -1;
  233.         }
  234.  
  235.       if (HANDLER_NIL (f) || f->f_type != DTYPE_FILE)
  236.         {
  237.           errno = EOPNOTSUPP;
  238.       KPRINTF (("&errno = %lx, errno = %ld\n", &errno, errno));
  239.       return -1;
  240.     }
  241.  
  242.       bzero (buf, sizeof (struct statfs));
  243.       buf->f_fsid.val[1] = 0;
  244.       buf->f_fsid.val[0] = (long) f->f_fh->fh_Type;
  245.       /* could probably use less drastic measures under 2.0... */
  246.       Forbid ();
  247.       dl = DOSBase;
  248.       rn = (struct RootNode *) dl->dl_Root;
  249.       di = BTOCPTR (rn->rn_Info);
  250.       for (dv = BTOCPTR (di->di_DevInfo); dv; dv = BTOCPTR (dv->dvi_Next))
  251.         {
  252.           if (dv->dvi_Type == DLT_DEVICE && 
  253.           (struct MsgPort *) dv->dvi_Task == f->f_fh->fh_Type)
  254.         {
  255.           char *name = BTOCPTR (dv->dvi_Name);
  256.           int len = (MNAMELEN - 2 < name[0]) ? MNAMELEN - 2 : name[0];
  257.  
  258.           bcopy (name + 1, buf->f_mntonname + 1, len);
  259.           buf->f_mntonname[0] = '/';
  260.           buf->f_mntonname[len + 1] = 0;
  261.           break;
  262.         }
  263.     }
  264.       Permit ();
  265.  
  266.       if (! dv)
  267.     {
  268.       errno = EOPNOTSUPP;
  269.       KPRINTF (("&errno = %lx, errno = %ld\n", &errno, errno));
  270.           return -1;
  271.         }
  272.  
  273.       info = alloca (sizeof (*info) + 2);
  274.       info = LONG_ALIGN (info);
  275.  
  276.       sp = alloca (sizeof (*sp) + 2);
  277.       sp = LONG_ALIGN (sp);
  278.       __init_std_packet (sp);
  279.  
  280.       internal_statfs (buf, info, sp);
  281.  
  282.       return 0;
  283.     }
  284.     
  285.   errno = EBADF;  
  286.   KPRINTF (("&errno = %lx, errno = %ld\n", &errno, errno));
  287.   return -1;
  288. }
  289.  
  290.  
  291. int
  292. statfs (const char *path, struct statfs *buf)
  293. {
  294.   struct MsgPort *handler;
  295.   BPTR lock;
  296.   int omask, err;
  297.   struct DosLibrary *dl;
  298.   struct RootNode *rn;
  299.   struct DosInfo *di;
  300.   struct DevInfo *dv;
  301.   extern struct ixemul_base *ixemulbase;
  302.   
  303.   struct InfoData *info;
  304.   struct StandardPacket *sp;
  305.  
  306.   omask = syscall (SYS_sigsetmask, ~0);
  307.   lock = __lock ((char *)path, ACCESS_READ);
  308.   handler = lock ? ((struct FileLock *) BTOCPTR (lock))->fl_Task : 0;
  309.   err = __ioerr_to_errno (IoErr ());
  310.   if (lock)
  311.     __unlock (lock);
  312.   syscall (SYS_sigsetmask, omask);
  313.   
  314.   if (! handler)
  315.     {
  316.       errno = err;
  317.       KPRINTF (("&errno = %lx, errno = %ld\n", &errno, errno));
  318.       return -1;
  319.     }
  320.   else
  321.     {
  322.       if (! buf)
  323.         {
  324.           errno = EFAULT;
  325.       KPRINTF (("&errno = %lx, errno = %ld\n", &errno, errno));
  326.           return -1;
  327.         }
  328.  
  329.       bzero (buf, sizeof (struct statfs));
  330.       buf->f_fsid.val[1] = 0;
  331.       buf->f_fsid.val[0] = (long) handler;
  332.       /* could probably use less drastic measures under 2.0... */
  333.       Forbid ();
  334.       dl = DOSBase;
  335.       rn = (struct RootNode *) dl->dl_Root;
  336.       di = BTOCPTR (rn->rn_Info);
  337.       for (dv = BTOCPTR (di->di_DevInfo); dv; dv = BTOCPTR (dv->dvi_Next))
  338.         {
  339.           if (dv->dvi_Type == DLT_DEVICE && 
  340.           (struct MsgPort *) dv->dvi_Task == handler)
  341.         {
  342.           char *name = BTOCPTR (dv->dvi_Name);
  343.           int len = (MNAMELEN - 2 < name[0]) ? MNAMELEN - 2 : name[0];
  344.  
  345.           bcopy (name + 1, buf->f_mntonname + 1, len);
  346.           buf->f_mntonname[0] = '/';
  347.           buf->f_mntonname[len + 1] = 0;
  348.           break;
  349.         }
  350.     }
  351.       Permit ();
  352.  
  353.       if (! dv)
  354.     {
  355.       errno = EOPNOTSUPP;
  356.       KPRINTF (("&errno = %lx, errno = %ld\n", &errno, errno));
  357.           return -1;
  358.         }
  359.  
  360.       info = alloca (sizeof (*info) + 2);
  361.       info = LONG_ALIGN (info);
  362.  
  363.       sp = alloca (sizeof (*sp) + 2);
  364.       sp = LONG_ALIGN (sp);
  365.       __init_std_packet (sp);
  366.  
  367.       internal_statfs (buf, info, sp);
  368.  
  369.       return 0;
  370.     }
  371. }
  372.